package com.comment.service.impl;

import com.alibaba.fastjson.JSON;
import com.comment.dtos.CommentLikeDto;
import com.comment.dtos.CommentListDto;
import com.comment.dtos.CommentSaveDto;
import com.comment.pojos.ApComment;
import com.comment.pojos.ApCommentLike;
import com.comment.pojos.ApCommentVo;
import com.comment.service.CommentService;
import com.heima.common.aliyun.GreenTextScan;
import com.heima.feign.client.ApUserClient;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.ApThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
public class CommentServiceImpl implements CommentService {
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private ApUserClient apUserClient;

    @Autowired
    private GreenTextScan textScan;

    /**
     * 创建评论
     * @param dto
     * @return
     */
    @Override
    public ResponseResult saveComment(CommentSaveDto dto) {
        ApUser apUser = ApThreadLocalUtil.getApUser();
        if(apUser == null && apUser.getId() == 0){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        if(dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        if (dto.getContent() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID,"评论内容不能为空");
        }
        if(dto.getArticleId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }
        // 1,先从redis中查询用户信息,没有再调用接口查询
        String userkey = "LOGIN_USER_" + apUser.getId();
        String userInfo = redisTemplate.opsForValue().get(userkey);
        if(StringUtils.isBlank(userInfo)){
            // 从远程服务获取用户信息
            ResponseResult<ApUser> user = apUserClient.findUserById(apUser.getId().longValue());
            if(user.getCode() == 200 && user.getData() != null){
                apUser = user.getData();
                // 存入redis,设置指定时间
                redisTemplate.opsForValue().set(userkey, JSON.toJSONString(apUser),2, TimeUnit.HOURS);
            }
        }else{
            // 存在信息代表已经登陆,直接从redis获取即可
            apUser = JSON.parseObject(userInfo, ApUser.class);
        }
        // 过滤文本信息
        Boolean aBoolean = this.scanTextFilter(dto.getContent());
        if(!aBoolean){
            return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_BLOCK);
        }
        //保存数据到数据库中
        ApComment apComment = new ApComment();
        apComment.setUserId(apUser.getId());
        apComment.setNickName(apUser.getName());
        apComment.setContent(dto.getContent());
        apComment.setTargetId(dto.getArticleId().toString());
        apComment.setCreatedTime(new Date());
        apComment.setUpdatedTime(new Date());
        apComment.setImage(apUser.getImage());
        apComment.setLikes(0);
        apComment.setReply(0);
        mongoTemplate.insert(apComment);
        return ResponseResult.okResult("评论成功");
    }

    private Boolean scanTextFilter(String content) {
        Boolean flag=true;
        try {
            Map map = textScan.greeTextScan(content);
            if(map!=null && !map.get("suggestion").equals("pass")){//表示违规
                flag=false;
            }
        } catch (Exception e) {
            e.printStackTrace();
            flag=false;
        }
        return flag;
    }

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        if(dto == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        if(dto.getCommentId() == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApUser apUser = ApThreadLocalUtil.getApUser();
        if(apUser == null && apUser.getId() != null){
            return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);
        }
        //判断当前评论信息是否存在，如果不存在，直接返回
        ApComment comment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(comment == null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST); // 评论内容不存在
        }
        // 查询redis,是否有点赞过
        String comment_likes_key="COMMENT_LIKE_"+apUser.getId();
        Boolean memberFlag = redisTemplate.opsForSet().isMember(comment_likes_key, dto.getCommentId());
        if(memberFlag && dto.getOperation()==0){
            return ResponseResult.errorResult(AppHttpCodeEnum.COMMENT_LIKES_END_SUCCESS); // 已赞
        }
        if(memberFlag && dto.getOperation()==1){
            // 取消点赞
            // 1, 删除redis
            redisTemplate.opsForSet().remove(comment_likes_key, dto.getCommentId());
            // 删除mongodb中的评论集合,
            mongoTemplate.remove(
                    Query.query(
                            Criteria.where("userId").is(apUser.getId()).and("targetId").is(dto.getCommentId()))
                            , ApCommentLike.class);
            // mongoDB点赞数减1
            Update update = new Update();
            update.inc("likes",-1);
            mongoTemplate.updateFirst(
                    Query.query(
                            Criteria.where("id").is(dto.getCommentId())
                    ),update
                    ,ApComment.class
            );
        }
        // 第一次点赞
        if(!memberFlag && dto.getOperation()==0){
            // 添加到redis
            redisTemplate.opsForSet().add(comment_likes_key, dto.getCommentId());
            // 添加到mongoDB
            ApCommentLike apCommentLike = new ApCommentLike();
            apCommentLike.setTargetId(dto.getCommentId());
            apCommentLike.setUserId(apUser.getId());
            apCommentLike.setCreatedTime(new Date());
            mongoTemplate.insert(apCommentLike);
            // 再给评论的数据点赞数加1
            Query query = Query.query(
                    Criteria.where("id").is(comment.getId())
            );
            Update update = new Update().inc("likes",1);
            mongoTemplate.updateFirst(query, update, ApComment.class);
        }
        // 返回数据
        ApComment comment1 = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        Map map = new HashMap();
        map.put("likes",comment1.getLikes());
        return ResponseResult.okResult(map);
    }

    @Override
    public ResponseResult findByArticleId(CommentListDto dto) {
        if (dto.getArticleId() == null) {
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        if (dto.getSize() == null || dto.getSize() == 0) {
            dto.setSize(10);
        }
        dto.setSize(Math.min(dto.getSize(), 50));
        Query query = Query.query(
                Criteria.where("targetId").is(dto.getArticleId().toString())
                        .and("createdTime").lt(dto.getMinDate()))
                .with(Sort.by(Sort.Direction.DESC, "createdTime"))
                .limit(dto.getSize());
        List<ApComment> list = mongoTemplate.find(query, ApComment.class);
        if(list == null && list.size()<0){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST);
        }
        //如果此刻是游客登录的话，则直接返回评论列表
        ApUser user = ApThreadLocalUtil.getApUser();
        if(user.getId()==0){
            return ResponseResult.okResult(list);
        }
        // 查询左右的点赞
        String key="COMMENT_LIKE_"+user.getId();
        //根据key查询出所有的值
        Set<String> likeList = redisTemplate.opsForSet().members(key);
        if(likeList == null){
            return ResponseResult.okResult(list);
        }
        List<ApCommentVo> discuzList = list.stream().map(commemtlist -> {
            ApCommentVo vo = new ApCommentVo();
            BeanUtils.copyProperties(commemtlist, vo);
            if (likeList.contains(commemtlist.getId())) {
                vo.setOperation((short) 0);
            }
            return vo;
        }).collect(Collectors.toList());


        return ResponseResult.okResult(discuzList);
    }
}
